#include "signal_handler.hpp"
#include <unistd.h>
#include <fcntl.h>
#include <stdexcept>
#include "logger.hpp"

int SignalHandler::signal_pipe_[2] = {-1, -1};

SignalHandler::SignalHandler(EventLoop& loop) : loop_(loop) {
    if (pipe(signal_pipe_) == -1) {
        throw std::runtime_error("Failed to create signal pipe");
    }
    
    // 设置管道为非阻塞
    int flags = fcntl(signal_pipe_[0], F_GETFL, 0);
    fcntl(signal_pipe_[0], F_SETFL, flags | O_NONBLOCK);
    
    // 注册管道读事件
    loop_.add(signal_pipe_[0], EPOLLIN | EPOLLET, [this](uint32_t /*events*/) {
        // events: epoll事件类型，表示文件描述符上发生的事件
        char buf[1024];
        while (read(signal_pipe_[0], buf, sizeof(buf)) > 0) {
            int signum = static_cast<int>(buf[0]);  // signum: 信号编号，表示具体的信号类型
            onSignal(signum);
        }
    });
}

SignalHandler::~SignalHandler() {
    if (signal_pipe_[0] != -1) {
        close(signal_pipe_[0]);
        close(signal_pipe_[1]);
    }
}

void SignalHandler::registerSignal(int signum, SignalCallback callback) {
    struct sigaction sa;
    sa.sa_handler = handleSignal;
    sa.sa_flags = SA_RESTART;
    sigemptyset(&sa.sa_mask);
    
    if (sigaction(signum, &sa, nullptr) == -1) {
        throw std::runtime_error("Failed to register signal handler for signal: " + std::to_string(signum));
    }
    
    callbacks_[signum] = std::move(callback);
    Logger::info("Registered handler for signal: {}", signum);
}

void SignalHandler::removeSignal(int signum) {
    struct sigaction sa;
    sa.sa_handler = SIG_DFL;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    
    if (sigaction(signum, &sa, nullptr) == -1) {
        throw std::runtime_error("Failed to remove signal handler");
    }
    
    callbacks_.erase(signum);
}

void SignalHandler::handleSignal(int signum) {
    if (signal_pipe_[1] != -1) {
        char buf[1] = {static_cast<char>(signum)};
        write(signal_pipe_[1], buf, 1);
    }
}

void SignalHandler::onSignal(int signum) {
    auto it = callbacks_.find(signum);
    if (it != callbacks_.end()) {
        it->second(signum);
    } else {
        // 不能处理的信号，打印一个警告
        Logger::critical("Unhandled signal: {}", signum);
    }
} 